package org.example.transaction;

import com.alibaba.druid.pool.xa.DruidXADataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlXAConnection;
import com.mysql.jdbc.jdbc2.optional.MysqlXid;
import lombok.extern.slf4j.Slf4j;

import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

@Slf4j
public class XADataSourceTest {

    private static final String URL = "jdbc:mysql://192.168.209.246:3306/simple_im?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC";

    private static final String USERNAME = "root";

    private static final String PASSWORD = "Infra5@Gep0int";

    public static void main(String[] args) throws Exception {
        boolean writeLog = true;

        // 数据源1
        Connection conn1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        XAConnection xaConn1 = new MysqlXAConnection((com.mysql.jdbc.Connection)conn1, writeLog);
        XAResource rm1 = xaConn1.getXAResource();

        // 数据源2
        Connection conn2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        XAConnection xaConn2 = new MysqlXAConnection((com.mysql.jdbc.Connection)conn2, writeLog);
        XAResource rm2 = xaConn2.getXAResource();

        // 应用程序请求事务管理器执行一个分布式事务，事务管理器生成全局事务ID
        byte[] gtrid = "binghe123".getBytes(StandardCharsets.UTF_8);
        int formatId = 1;
        Xid xid1 = null;
        Xid xid2 = null;

        // 事务管理器生成rm1上的事务分支id
        byte[] bqual1 = "binghe001".getBytes(StandardCharsets.UTF_8);
        xid1 = new MysqlXid(gtrid, bqual1, formatId);
        // 执行rm1上的事务分支
        rm1.start(xid1, XAResource.TMNOFLAGS);
        PreparedStatement ps1 = conn1.prepareStatement("insert into account(name, balance) values('1748', 100)");
        ps1.execute();
        rm1.end(xid1, XAResource.TMSUCCESS);

        // 事务管理器生成rm2上的事务分支id
        byte[] bqual2 = "binghe002".getBytes(StandardCharsets.UTF_8);
        xid2 = new MysqlXid(gtrid, bqual2, formatId);
        rm2.start(xid2, XAResource.TMNOFLAGS);
        PreparedStatement ps2 = conn2.prepareStatement("insert into account(name, balance) values('1752', 100)");
        ps2.execute();
        rm2.end(xid2, XAResource.TMSUCCESS);

        // 两阶段提交
        // 第一阶段：通知所有的资源管理器准备提交事务分支
        int rm1_prepare = rm1.prepare(xid1);
        int rm2_prepare = rm2.prepare(xid2);
        // 第二阶段：提交所有事务分支
        boolean onePhase = false;
        if (rm1_prepare == XAResource.XA_OK && rm2_prepare == XAResource.XA_OK) {
            rm1.commit(xid1, onePhase);
            rm2.commit(xid2, onePhase);
        } else {
            rm1.rollback(xid1);
            rm2.rollback(xid2);
        }
    }
}
